package com.xiaohu.gateway.filter;

import cn.hutool.core.lang.hash.Hash;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaohu.common.dao.Tourist;
import com.xiaohu.common.dao.User;
import com.xiaohu.common.mapper.TouristMapper;
import com.xiaohu.common.mapper.UserMapper;
import com.xiaohu.common.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Component
public class DestinyCoordinateGateWayFilter implements GlobalFilter, Ordered {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TouristMapper touristMapper;

    /**
     * gateway的拦截器,所有请求网关的接口都会通过这个拦截器
     * @param exchange 请求响应体
     * @param chain 调用链
     * @return 通过chain放行
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {


        /**
         * 1. 判断是否携带accessKey以及证书
         * 2. 验证accessKey和secretKey
         * 3. 如果没有携带统计IP 每个IP 调用50次
         * 4. 计数
         */
        System.out.println("进入拦截");
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        HttpHeaders headers = exchange.getRequest().getHeaders();
        // IP
        String IP = Objects.requireNonNull(headers.getHost()).getHostString();
        // AK
        String accessKey = headers.getFirst("accessKey");
        // 证书
        String certificate = headers.getFirst("certificate");
        // 后门
        String hm = headers.getFirst("hm");
        if (StrUtil.isNotEmpty(hm)) {
            return chain.filter(exchange);
        }
        // 有AK 和 证书的情况
        if (StrUtil.isNotEmpty(accessKey) && StrUtil.isNotEmpty(certificate)) {
            // 根据AK查找SK
            User user = userMapper.selectSecretKeyByAccessKey(accessKey);
            if (ObjectUtil.isNotEmpty(user)) {
                if (StrUtil.equals(headers.getFirst("certificate"), md5.digestHex(user.getSecretKey()))) {
                    // 验证AK次数
                    if (user.getTotal() < 10) {
                        // AK SK 验证成功 添加次数
                        // TODO 这里应该添加分布式锁的 保证接口不会被多刷
                        userMapper.increaseUserTotalByAccessKey(accessKey);
                        return chain.filter(exchange);
                    } else {
                        // 没有次数
                        return noPower(exchange, "次数不够了");
                    }
                } else {
                    // 证书效验失败
                    return noPower(exchange, "证书效验失败");
                }
            } else {
                // 非法的AccessKey
                return noPower(exchange, "非法的AccessKey");
            }
        }
        // 直接调用的情况下
        LambdaQueryWrapper<Tourist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Tourist::getTouristName, IP);
        if (touristMapper.selectOne(wrapper) == null) {
            Tourist tourist = new Tourist();
            tourist.setTouristName(IP);
            tourist.setTotal(0);
            touristMapper.insert(tourist);
            return chain.filter(exchange);
        } else if (touristMapper.selectTouristTotal(IP) < 10) {
            touristMapper.touristTotalAddOneByTouristName(IP);
            return chain.filter(exchange);
        }else {
            return noPower(exchange, "次数不够了!!");
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }


    /**
     * 网关拒绝，返回Result
     *
     * @param
     */
    private Mono<Void> noPower(ServerWebExchange serverWebExchange, String mes) {
        // 权限不够拦截
        Result data = Result.fail(403, mes);
        DataBuffer buffer = serverWebExchange.getResponse().bufferFactory().wrap(JSONUtil.toJsonStr(data).getBytes(StandardCharsets.UTF_8));
        ServerHttpResponse response = serverWebExchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));

    }
}
